package com.cloudkinto.service.stock.impl;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.BeanConvert;
import com.cloudkinto.common.DicBusinessConstant;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.ExcelUtils;
import com.cloudkinto.common.utils.StringsUtil;
import com.cloudkinto.common.utils.ali.AliOss;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.extentity.StockRecordPageDto;
import com.cloudkinto.extentity.StockSnapshotPageDto;
import com.cloudkinto.extentity.stock.ShopStockRecordDto;
import com.cloudkinto.service.company.CompanyService;
import com.cloudkinto.service.dic.DicBusinessItemService;
import com.cloudkinto.service.dic.vo.LanguageValueEntity;
import com.cloudkinto.service.finance.vo.IdAndNameEntity;
import com.cloudkinto.service.orderoutput.OrderOutputService;
import com.cloudkinto.service.orderoutput.vo.OrderOutputAddReq;
import com.cloudkinto.service.orderoutput.vo.OrderOutputPackageAddReq;
import com.cloudkinto.service.orderoutput.vo.OrderOutputProductAddReq;
import com.cloudkinto.service.region.JpRegionService;
import com.cloudkinto.service.shop.ShopService;
import com.cloudkinto.service.stock.StockLogService;
import com.cloudkinto.service.stock.StockRecordService;
import com.cloudkinto.service.stock.vo.FreezeStockReq;
import com.cloudkinto.service.stock.vo.StockSnapshotExportVo;
import com.cloudkinto.service.stock.vo.record.*;
import com.cloudkinto.service.storage.StorageService;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author 张永远
 * @since 2020-06-10
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class StockRecordServiceImpl extends ServiceImpl<StockRecordDao, StockRecordDo> implements StockRecordService {
    @Autowired
    private StockRecordDao dao;
    @Autowired
    private ShopDao shopDao;
    @Autowired
    private StorageDao storageDao;
    @Autowired
    private StorageService storageService;
    @Autowired
    private OrderOutputDao orderOutputDao;
    @Autowired
    private OrderOutputPackageDao orderOutputPackageDao;
    @Autowired
    private OrderOutputProductDao orderOutputProductDao;
    @Autowired
    private ProductInfoDao productInfoDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private JpRegionService regionService;
    @Autowired
    private ShopService shopService;
    @Autowired
    private OrderOutputService orderOutputService;
    @Autowired
    private CompanyDao companyDao;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private StockLogService stockLogDao;
    @Autowired
    private DicBusinessItemDao dicBusinessItemDao;
    @Value("${gbc.uploadPath.fileUrl}")
    private String fileUrl;

    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;
    @Autowired
    private DicBusinessItemService dicBusinessItemService;


    @Override
    public SingleResult add(StockRecordAddReq req, Long userId) {
        StockRecordDo stockRecordDo = new StockRecordDo();
        BeanUtils.copyProperties(req, stockRecordDo);
        stockRecordDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        verfyExist(stockRecordDo.getProductInfoId(), stockRecordDo.getShopId(), stockRecordDo.getStorageId(), null);
        dao.insert(stockRecordDo);
        stockLogDao.saveAutoSendOutLog(req.getProductInfoId(), stockRecordDo.getShopId(), stockRecordDo.getStorageId(),
                stockRecordDo.getCanSellCount(), req.getCanSellCount(), stockRecordDo.getCompanyId(), userId, "库存初始化");
        return SingleResult.success("新增成功", stockRecordDo);
    }

    private void verfyExist(Long productInfoId, Long shopId, Long storageId, Long id) {
        QueryWrapper<StockRecordDo> wrapper = new QueryWrapper<>();
        wrapper.eq("product_info_id", productInfoId);
        wrapper.eq("shop_id", shopId);
        wrapper.eq("storage_id", storageId);
        if (id != null)
            wrapper.ne("id", id);
        List<StockRecordDo> list = dao.selectList(wrapper);
        if (list == null || list.size() < 1) {

        } else {
            throw new BizException(SysConstant.StockRecord_Error);
        }
    }


    @Override
    public SingleResult update(StockRecordUpdateReq req, Long userId) {
        return SingleResult.failure("无权限，请去jdy系统仓库配置-库位一览中申请盘点");
//        StockRecordDo stockRecordDo = dao.selectById(req.getId());
//        verfyExist(req.getProductInfoId(), req.getShopId(), req.getStorageId(), req.getId());
//        if (!stockRecordDo.getProductInfoId().equals(req.getProductInfoId()) ||
//                !stockRecordDo.getStorageId().equals(req.getStorageId()) ||
//                !stockRecordDo.getShopId().equals(req.getShopId())) {
//            stockLogDao.saveAutoSendOutLog(req.getProductInfoId(), req.getShopId(), req.getStorageId(),
//                    req.getCanSellCount(), req.getCanSellCount(), req.getCompanyId(), userId, StringUtils.isBlank(req.getContent()) ? "库存盘点" : req.getContent());
//            stockLogDao.saveAutoSendOutLog(1, req.getProductInfoId(), req.getShopId(), req.getStorageId(),
//                    req.getCanotSellCount(), req.getCanotSellCount(), req.getCompanyId(), userId, StringUtils.isBlank(req.getContent()) ? "库存盘点" : req.getContent());
//            stockLogDao.saveAutoSendOutLog(stockRecordDo.getProductInfoId(), stockRecordDo.getShopId(), stockRecordDo.getStorageId(),
//                    -stockRecordDo.getCanSellCount(), 0, stockRecordDo.getCompanyId(), userId, StringUtils.isBlank(req.getContent()) ? "库存盘点" : req.getContent());
//            stockLogDao.saveAutoSendOutLog(1, stockRecordDo.getProductInfoId(), stockRecordDo.getShopId(), stockRecordDo.getStorageId(),
//                    -stockRecordDo.getCanotSellCount(), 0, stockRecordDo.getCompanyId(), userId, StringUtils.isBlank(req.getContent()) ? "库存盘点" : req.getContent());
//        } else {
//            stockLogDao.saveAutoSendOutLog(req.getProductInfoId(), stockRecordDo.getShopId(), stockRecordDo.getStorageId(),
//                    req.getCanSellCount() - stockRecordDo.getCanSellCount(), req.getCanSellCount(), stockRecordDo.getCompanyId(), userId, StringUtils.isBlank(req.getContent()) ? "库存盘点" : req.getContent());
//            stockLogDao.saveAutoSendOutLog(1, req.getProductInfoId(), stockRecordDo.getShopId(), stockRecordDo.getStorageId(),
//                    req.getCanotSellCount() - stockRecordDo.getCanotSellCount(), req.getCanotSellCount(), stockRecordDo.getCompanyId(), userId, StringUtils.isBlank(req.getContent()) ? "库存盘点" : req.getContent());
//        }
//        BeanUtils.copyProperties(req, stockRecordDo);
//        stockRecordDo.setUpdateBy(userId);
//        stockRecordDo.setUpdateTime(new Date());
//        dao.updateById(stockRecordDo);
//        return SingleResult.success("更新成功", stockRecordDo);
//
    }

    @Override
    public SingleResult addInit() {
        Map result = new HashMap();

//        List<Map> shopList = new ArrayList<>();
//        List<ShopDo> shopDoList = shopDao.selectList(null);
//        if (!CollectionUtils.isEmpty(shopDoList)) {
//            shopDoList.forEach(shopDo -> {
//                Map map = new HashMap();
//                map.put("id", shopDo.getId());
//                map.put("value", shopDo.getShopName());
//                shopList.add(map);
//            });
//        }

        List<Map> storageList = new ArrayList<>();
        List<StorageDo> storageDoList = storageDao.selectList(null);
        if (!CollectionUtils.isEmpty(storageDoList)) {
            storageDoList.forEach(storageDo -> {
                Map map = new HashMap();
                map.put("id", storageDo.getId());
                map.put("value", storageDo.getStorageName());
                storageList.add(map);
            });
        }

//        List<Map> companyList = new ArrayList<>();
//        List<CompanyDo> companyDoList = companyDao.selectList(null);
//        if (!CollectionUtils.isEmpty(companyDoList)) {
//            companyDoList.forEach(companyDo -> {
//                Map map = new HashMap();
//                map.put("id", companyDo.getId());
//                map.put("value", companyDo.getCompanyCode());
//                companyList.add(map);
//            });
//        }
//        result.put("shopList", shopList);
        result.put("storageList", storageList);
        result.put("companyTree", companyService.tree());
        return SingleResult.success(result);
    }

    @Override
    public SingleResult updateInit(Long id) {
        Map map = (Map) addInit().getData();

        StockRecordDo entityDo = dao.selectById(id);
        StockRecordDetailRes res = new StockRecordDetailRes();
        BeanUtils.copyProperties(entityDo, res);
        ProductInfoDo productInfoDo = productInfoDao.selectById(entityDo.getProductInfoId());
        if (productInfoDo != null) {
            res.setCommoditySku(productInfoDo.getCommoditySku());
        }
        CompanyDo companyDo = companyDao.selectById(entityDo.getCompanyId());
        if (companyDo != null) {
            res.setCompanyCode(companyDo.getCompanyCode());
        }
        ShopDo shopDo = shopDao.selectById(entityDo.getShopId());
        if (shopDo != null) {
            res.setShopName(shopDo.getShopName());
        }
        map.put("detail", res);
        return SingleResult.success(map);
    }

    @Override
    public Object update(Object req, Long userId) {
        /*StockRecordDo entityDo = dao.selectById(req.getId());
        BeanUtils.copyProperties(req, entityDo);
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return handlerUpdateAfter(entityDo);*/
        return null;
    }

    //编辑校验
    private void updateCheck(Object req) {

    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(StockRecordDo entityDo, Long userId) {
        entityDo.setUpdateBy(userId);
        entityDo.setUpdateTime(new Date());
    }

    //做修改之后要执行的业务定制处理
    private Object handlerUpdateAfter(StockRecordDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public int delete(Long id, Long userId) {
        StockRecordDo entityDo = dao.selectById(id);
        handlerDeleteBefore(entityDo, userId);
        dao.selectById(entityDo);
        return dao.deleteById(id);
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(StockRecordDo entityDo, Long userId) {
        entityDo.setDeleteBy(userId);
        entityDo.setDeleteTime(new Date());
    }

    @Override
    public StockRecordDetailRes detail(Long id) {
        return null;
    }

    //查询明细之后要执行的业务定制处理
    private StockRecordDetailRes handlerDetailAfter(StockRecordDetailRes res) {
        return res;
    }

    @Override
    public SingleResult pageInit(Long companyId, Long userId) {
        Map map = new HashMap();
        List<Map> shopList = new ArrayList<>();
        List<ShopDo> shopDoList = shopDao.selectList(null);
        if (!CollectionUtils.isEmpty(shopDoList)) {
            for (ShopDo shopDo : shopDoList) {
                Map shopMap = new HashMap();
                shopMap.put("id", shopDo.getId());
                shopMap.put("value", shopDo.getShopName());
                shopList.add(shopMap);
            }
        }
        map.put("shopList", shopList);
        map.put("productTypeList", dicBusinessItemService.getDicItemList(DicBusinessConstant.productType));
        map.put("storageList", storageService.getStorageList());
        map.put("companyTree", companyService.getList());

        return SingleResult.success(map);
    }

    @Override
    public List<StockRecordPageRes> getList(Map<String, String> map) {
        List<StockRecordPageDto> pageDtoList = dao.listPage(map);
        List<StockRecordPageRes> resList = handlerListAfter(pageDtoList);
        return resList;
    }

    @Override
    public PageResult<StockRecordPageRes> getListPage(Map<String, String> map) {
        IPage<StockRecordPageDto> page = pageInit(map);
        List<StockRecordPageDto> pageDtoList = dao.listPage(page, map);
        List<StockRecordPageRes> resList = handlerListAfter(pageDtoList);
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }


    @Override
    public SingleResult sendOutInit() {
        Map map = new HashMap();
        map.put("regioon", regionService.getList(new HashMap<>()));
        List<LanguageValueEntity> idAndNameEntities = new ArrayList<>();
        idAndNameEntities.add(new LanguageValueEntity(0, "SHIPMENT_TYPE_0"));
        idAndNameEntities.add(new LanguageValueEntity(1, "SHIPMENT_TYPE_1"));
        map.put("shipment", idAndNameEntities);
        return SingleResult.success(map);
    }

    @Override
    public void feeDeduction() {
        List<StockRecordDo> stockRecordDos = dao.selectList(null);
        if (!CollectionUtils.isEmpty(stockRecordDos)) {
            for (StockRecordDo stockRecordDo : stockRecordDos) {

            }
        }
    }

    @Override
    public SingleResult sendOut(StockRecordSendReq req, Long userId, Long companyId) {
        StockRecordDo stockRecordDo = dao.selectById(req.getId());
        ProductInfoDo productInfoDo = productInfoDao.selectById(stockRecordDo.getProductInfoId());
        OrderOutputAddReq orderInputDo = new OrderOutputAddReq();
//        orderInputDo.setOrderType(1);//一件代发
        orderInputDo.setSendDate(new Date());
        orderInputDo.setShopId(stockRecordDo.getShopId());
        orderInputDo.setStorageId(stockRecordDo.getStorageId());
        orderInputDo.setCompanyId(stockRecordDo.getCompanyId());
        orderInputDo.setReceiverName(req.getReceiveName());
        orderInputDo.setTelPhone(req.getTelephone());
        orderInputDo.setPostCode(req.getPostCode());
        orderInputDo.setArea(req.getArea());
        orderInputDo.setAddress(req.getReceiveAddress());
        orderInputDo.setTips(req.getRemark());
        orderInputDo.setCod(req.getCod());
        if (StringUtils.isNotBlank(req.getDeliveryDate())) {
            orderInputDo.setDeliveryDate(req.getDeliveryDate());
        }
        orderInputDo.setDeliveryTime(req.getDeliveryTime());
        orderInputDo.setShipmentType(req.getShipmentType());
        orderInputDo.setOrderNo(req.getOrderNumber());
        List<OrderOutputPackageAddReq> packageAddList = new ArrayList<>();
        OrderOutputPackageAddReq packageAdd = new OrderOutputPackageAddReq();
        orderInputDo.setPackageList(packageAddList);
        OrderOutputPackageDo packageDo = new OrderOutputPackageDo();
//        packageDo.setLength(null);
//        packageDo.setWidth(null);
//        packageDo.setHeight(null);
//        packageDo.setHeight(null);
//        packageDo.setWeight(null);
        packageDo.setCreateTime(new Date());
        packageDo.setCreateBy(userId);
        packageDo.setDeleteFlag(0);

        List<OrderOutputProductAddReq> productDos = new ArrayList<>();
        OrderOutputProductAddReq productDo = new OrderOutputProductAddReq();
        productDo.setPackageId(packageDo.getId());
        productDo.setProductId(stockRecordDo.getProductInfoId());
        productDo.setCount(req.getCount());
        productDos.add(productDo);
        packageAdd.setProductList(productDos);
        packageAddList.add(packageAdd);
        String value = orderOutputService.add(orderInputDo, userId);
        if (value == null) {
            return SingleResult.success();
        } else {
            return SingleResult.success(value, null);
        }
    }

    //查询分页列表之后对列表数据的处理
    private List<StockRecordPageRes> handlerListAfter(List<StockRecordPageDto> list) {
        List<StockRecordPageRes> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            for (StockRecordPageDto pageDto : list) {
                StockRecordPageRes res = new StockRecordPageRes();
                res.setId(pageDto.getId());
                res.setStorageId(pageDto.getStorageId());
                res.setProductId(pageDto.getProductId());
                res.setCanotSellCount(pageDto.getCanotSellCount());
                res.setProductInfoId(pageDto.getProductInfoId());
                res.setCanSellCount(pageDto.getCanSellCount());
                res.setCommoditySku(pageDto.getCommoditySku());
                res.setStorageSku(pageDto.getStorageSku());
                res.setProductName(pageDto.getProductName());
                res.setNoDelivered(pageDto.getNoDelivered() + pageDto.getTurnFba());
                res.setJustNoDelivered(pageDto.getNoDelivered());
                res.setTurnFba(pageDto.getTurnFba());
                res.setInTransit(pageDto.getInTransit());
                res.setShopId(pageDto.getShopId());
                res.setFreezeCount(pageDto.getFreezeCount());

                res.setUpdateTime(pageDto.getUpdateTime());
                ShopDo shopDo = shopDao.selectById(pageDto.getShopId());
                if (shopDo != null) {
                    res.setShop(shopDo.getShopName());
                }
                StorageDo storageDo = storageDao.selectById(pageDto.getStorageId());
                if (storageDo != null) {
                    res.setStorage(storageDo.getStorageName());
                }
                CompanyDo companyDo = companyDao.selectById(pageDto.getCompanyId());
                if (companyDo != null) {
                    res.setCompanyCode(companyDo.getCompanyCode());
                }
                result.add(res);
            }
        }
        return result;
    }

    @Override
    public boolean turn2BadStock(String commoditySku, Long outputShopId, Long outputStorageId, int count, String orderNO, Long userId) {
        ProductInfoDo productInfoDo = productInfoDao.selectById(commoditySku);
        if (productInfoDo == null)
            return false;
        LambdaQueryWrapper<StockRecordDo> stockRecordWrapper = new LambdaQueryWrapper<>();
        stockRecordWrapper.eq(StockRecordDo::getProductInfoId, productInfoDo.getId())
                .eq(StockRecordDo::getShopId, outputShopId)
                .eq(StockRecordDo::getStorageId, outputStorageId)
                .last("limit 1");
        StockRecordDo stockRecordDo = dao.selectOne(stockRecordWrapper);
        if (stockRecordDo == null) {
            stockRecordWrapper = new LambdaQueryWrapper<>();
            stockRecordWrapper.eq(StockRecordDo::getProductInfoId, productInfoDo.getId())
                    .eq(StockRecordDo::getStorageId, outputStorageId)
                    .last("limit 1");
            stockRecordDo = dao.selectOne(stockRecordWrapper);
        }
        if (stockRecordDo == null) return true;
        stockRecordDo.setCanSellCount(stockRecordDo.getCanSellCount() - count);
        stockRecordDo.setCanotSellCount(stockRecordDo.getCanotSellCount() + count);
        updateById(stockRecordDo);
        stockLogDao.saveAutoSendOutLog(productInfoDo.getId(), outputShopId, outputStorageId, -count, stockRecordDo.getCanSellCount(), stockRecordDo.getCompanyId(), userId, orderNO);
        stockLogDao.saveAutoSendOutLog(1, productInfoDo.getId(), outputShopId, outputStorageId, count, stockRecordDo.getCanotSellCount(), stockRecordDo.getCompanyId(), userId, orderNO);
        return true;
    }

    private IPage<StockRecordPageDto> pageInit(Map<String, String> map) {
        IPage<StockRecordPageDto> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    /******************库存快照模块************************/
    private IPage<StockSnapshotPageDto> StockSnapshotPageInit(Map<String, String> map) {
        IPage<StockSnapshotPageDto> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    @Override
    public PageResult getStockSnapshotPage(Map<String, String> map) {
        IPage<StockSnapshotPageDto> page = StockSnapshotPageInit(map);
        List<StockSnapshotPageDto> resList = dao.getStockSnapshotList(page, map);
        for (StockSnapshotPageDto stockSnapshotPageDto : resList) {
            stockSnapshotPageDto.setStockType(StringsUtil.createI18Message(stockSnapshotPageDto.getStockType()));
        }
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    @Override
    public String exportExcel(Map<String, String> map, String fileName) throws IOException {
        List<StockSnapshotPageDto> list = dao.getStockSnapshotList(map);
        if (list.size() > 9999) {
            throw new BizException(SysConstant.File_Export_ToMuch, 10000);
        }
        List<StockSnapshotExportVo> exportVoList = new ArrayList<>();
        list.forEach(et -> {
            StockSnapshotExportVo exportVo = BeanConvert.INSTANCE.stockSnapshotExportVo(et);
            exportVoList.add(exportVo);
        });
        ExportParams exportParams = new ExportParams();
        exportParams.setCreateHeadRows(true);
        exportParams.setHeaderColor(IndexedColors.YELLOW.getIndex());

        ExcelUtils.exportExcelToSave(exportVoList, StockSnapshotExportVo.class, fileName, exportParams, filePathTemp);
        String objectNameTemporary = "";
        try {
            objectNameTemporary = AliOss.temporaryFile2(fileName, new File(filePathTemp + File.separator + fileName));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("导出文件失败" + e.getMessage());
        }
        return fileUrl + objectNameTemporary;
    }

    /**
     * 封装的 旧表扣减良品库存
     *
     * @param productInfoDo
     * @param storageId
     * @param shopId
     * @param quantity
     * @param outOrderNo
     * @param userId
     */
    @Override
    public void deduceGoodStock(ProductInfoDo productInfoDo, Long storageId, Long shopId, int quantity, String outOrderNo, Long userId) {
        LambdaQueryWrapper<StockRecordDo> stockWrapper = new LambdaQueryWrapper<>();
        stockWrapper.eq(StockRecordDo::getProductInfoId, productInfoDo.getId())
                .eq(StockRecordDo::getStorageId, storageId)
                .eq(StockRecordDo::getShopId, shopId);
        StockRecordDo stockRecordDo;
        //减去OMS库存表
        synchronized (this) {
            stockRecordDo = dao.selectOne(stockWrapper);
        }
        if (stockRecordDo == null || stockRecordDo.getCanSellCount() < quantity) {
            throw new BizException(SysConstant.Product_OmsStock_NotEnough_Sku, productInfoDo.getCommoditySku());
        }
//                stockRecordDo.setCanSellCount(stockRecordDo.getCanSellCount() - onceCount);
//                stockRecordDo.setUpdateTime(new Date());
//                mStockRecordDao.updateById(stockRecordDo);
        dao.updateStockById(stockRecordDo.getId(), quantity);

        stockLogDao.saveAutoSendOutLog(productInfoDo.getId(), stockRecordDo.getShopId(), stockRecordDo.getStorageId(),
                -quantity, stockRecordDo.getCanSellCount() - quantity, stockRecordDo.getCompanyId(), userId, outOrderNo);
    }


    /**
     * 封装的 旧表扣减良品库存
     *
     * @param storageId
     * @param shopId
     * @param quantity
     * @param outOrderNo
     * @param userId
     */
    @Override
    public void deduceGoodStock(Long productId, Long storageId, Long shopId, int quantity, String outOrderNo, Long userId) {
        ProductInfoDo productInfoDo = productInfoDao.selectObject(productId);
        if (productInfoDo == null) {
            throw new BizException(SysConstant.Product_NotExist);
        }
        this.deduceGoodStock(productInfoDo, storageId, shopId, quantity, outOrderNo, userId);
    }


    /**
     * 新增功能 冻结库存
     */
    @Override
    public void freezeStock(FreezeStockReq req, Long userId) {
        this.freezeStock(req.getProductId(), req.getStorageId(), req.getShopId(), req.getType(), req.getFreezeCount(), userId);
    }


    @Override
    public void freezeStock(Long productId, Long storageId, Long shopId, int type, int freezeCount, Long userId) {
        if (freezeCount == 0) {
            return;
        }

        ProductInfoDo productInfoDo = productInfoDao.selectObject(productId);
        if (productInfoDo == null) {
            throw new BizException(SysConstant.Product_NotExist);
        }
        LambdaQueryWrapper<StockRecordDo> stockWrapper = new LambdaQueryWrapper<>();
        stockWrapper.eq(StockRecordDo::getProductInfoId, productId)
                .eq(StockRecordDo::getStorageId, storageId)
                .eq(StockRecordDo::getShopId, shopId);
        StockRecordDo stockRecordDo;
        //减去OMS库存表
        synchronized (this) {
            stockRecordDo = dao.selectOne(stockWrapper);
        }
        if (stockRecordDo == null) {
            throw new BizException(SysConstant.Product_OmsStock_NotEnough_Sku, productInfoDo.getCommoditySku());
        }

        if (type == 0) {
            if (stockRecordDo.getCanSellCount() < freezeCount) {
                throw new BizException(SysConstant.Product_OmsStock_NotEnough_Sku, productInfoDo.getCommoditySku());
            }
            //冻结
            stockRecordDo.setCanSellCount(stockRecordDo.getCanSellCount() - freezeCount);
            stockRecordDo.setFreezeCount(stockRecordDo.getFreezeCount() + freezeCount);
        } else {
            //解冻
            if (stockRecordDo.getFreezeCount() < freezeCount) {
                throw new BizException(SysConstant.Product_OmsStock_NotEnough_Sku_Freeze, productInfoDo.getCommoditySku());
            }
            stockRecordDo.setCanSellCount(stockRecordDo.getCanSellCount() + freezeCount);
            stockRecordDo.setFreezeCount(stockRecordDo.getFreezeCount() - freezeCount);
        }
        dao.updateById(stockRecordDo);

        stockLogDao.saveAutoSendOutLog(productInfoDo.getId(), stockRecordDo.getShopId(), stockRecordDo.getStorageId(),
                -freezeCount, stockRecordDo.getCanSellCount(), stockRecordDo.getCompanyId(), userId, type == 0 ? "冻结库存" : "解冻库存");
    }


    /**
     * 冻结库存
     *
     * @param productId
     * @param userId
     */
    @Override
    public void freezeStock(Long productId, Long userId) {
        List<StockRecordDo> list = dao.selectList(new LambdaQueryWrapper<StockRecordDo>()
                .eq(StockRecordDo::getProductInfoId, productId));
        for (StockRecordDo recordDo : list) {
            if (recordDo.getCanSellCount() == 0) {
                continue;
            }
            this.freezeStock(productId, recordDo.getStorageId(), recordDo.getShopId(), 0, recordDo.getCanSellCount(), userId);
        }
    }


    @Override
    public List<ShopStockRecordDto> getStockRecord(Long productId, Long storageId, Integer type, String quantityType) {
        List<ShopStockRecordDto> list = dao.getShopStockList(productId, storageId, type, quantityType);
        return list;
    }
}
